home *** CD-ROM | disk | FTP | other *** search
- /* sc_extend.c
- gopher item subclass procedures for extended type */
-
- /*---------------------------------------------------------------*/
- /* Xgopher version 1.3 08 April 1993 */
- /* version 1.2 20 November 1992 */
- /* version 1.1 20 April 1992 */
- /* version 1.0 04 March 1992 */
- /* X window system client for the University of Minnesota */
- /* Internet Gopher System. */
- /* Allan Tuchman, University of Illinois at Urbana-Champaign */
- /* Computing and Communications Services Office */
- /* Copyright 1992, 1993 by */
- /* the Board of Trustees of the University of Illinois */
- /* Permission is granted to freely copy and redistribute this */
- /* software with the copyright notice intact. */
- /*---------------------------------------------------------------*/
-
- #include "osdep.h"
- #include "conf.h"
- #include "globals.h"
- #include "gopher.h"
- #include "appres.h"
- #include "typeres.h"
- #include "util.h"
- #include "status.h"
- #include "subst.h"
- #include "misc.h"
- #include "jobs.h"
- #include "sc_extend.h"
- #include "sc_extendP.h"
-
- #include <stdio.h>
- extern errno;
-
- static extTypeValue *etvList = NULL;
-
-
- #define PIPE_CHAR '|'
-
-
- /* forkAndExec
- fork off another process which will call system to execute a command */
-
- static PID_TYPE
- forkAndExec(cmd, tempName, forkErrno)
- char *cmd;
- char *tempName;
- int *forkErrno;
- {
- PID_TYPE pid;
-
-
- /* fprintf (stderr, "forkAndExec: %s\n", cmd); */
-
- *forkErrno = 0;
- if ((pid = fork()) == (PID_TYPE) 0) {
-
- /* we should immediately do a
- close (ConnectionNumber(XtDisplay(widget)));
- here. */
-
- system(cmd);
- if (tempName != (char *) NULL) {
- unlink (tempName);
- }
-
- /* the child's useful life is over */
-
- exit(0);
-
- } else if (pid < 0) {
- *forkErrno = errno;
- if (tempName != (char *) NULL) {
- unlink (tempName);
- }
- pid = ((PID_TYPE) 0);
- }
-
- return pid;
- }
-
-
- /* forkAndPipe
- fork off another process which will pipe stdin to another command */
-
- static PID_TYPE
- forkAndPipe(cmd, gi, forkErrno)
- char *cmd;
- gopherItemP gi;
- int *forkErrno;
- {
- char message[MESSAGE_STRING_LEN];
- FILE *cmdFile;
- int s;
- PID_TYPE pid;
-
- *forkErrno = 0;
- if ((pid = fork()) == (PID_TYPE) 0) {
-
- /* we should immediately do a
- close (ConnectionNumber(XtDisplay(widget)));
- here.
- */
-
- s = connectToSocket(gi->host, gi->port);
- if (s < 0) {
- networkError(s, gi->host, gi->port);
- return FALSE;
- }
-
- writeString(s, vStringValue(&(gi->selector)));
- writeString(s, EOL_STRING);
-
- cmdFile = popen(cmd, "w");
-
- if (cmdFile == (FILE *) NULL) {
- sprintf(message,
- "Unable to start the command (\'%s\')\n",
- cmd);
- fprintf(stderr, "%s\n", message);
- close (s);
- /* this is the child process */
- exit(-1);
- }
-
- GI_copyNetUntilEOF(s, cmdFile);
-
- close(s);
- pclose(cmdFile);
-
- /* the child's useful life is over */
-
- exit(0);
-
-
- } else if (pid < 0) {
- *forkErrno = errno;
- pid = ((PID_TYPE) 0);
- }
-
- return pid;
- }
-
-
- BOOLEAN
- issueCommand(gi, etv)
- gopherItemP gi;
- extTypeValue *etv;
- {
- scInfo *sc = gi->sc;
- char *cmd;
- char errorString[MESSAGE_STRING_LEN];
- char tempName[PATH_NAME_LEN];
- char message[MESSAGE_STRING_LEN];
- int tempFD;
- int s;
- char *path, *suffix = (char *) NULL;
-
-
- /* Three cases: 1) no data to be copied (e.g. a telnet session);
- 2) data copied to temp file first (e.g. text)
- 3) data piped from network to program (e.g. sound)
- */
-
-
- if (sc->copyProc == GI_noCopyItem) {
-
- /* ===== No Data needed ===== */
-
- int forkError;
-
- cmd = editCommand(gi, etv->execCommand, "", (char *) NULL);
- /* fprintf (stderr, "\tExecute the command\n\t%s\n\n", cmd); */
-
- sprintf(message, "Working on %s, please stand by",
- gi->sc->typeName);
- showStatus(message, STAT_TEMP_MESSAGE, (char *) NULL, 0);
-
- if ((etv->pid =
- forkAndExec(tildePath(cmd), (char *)NULL, &forkError))
- == 0) {
- etv->failed = TRUE;
- sprintf(message,
- "Error trying to start command for \'%s\' (error %d)\n\'%s\'\n",
- sc->typeName, errno, cmd);
- showError(message);
- }
-
- if (etv->pid != (PID_TYPE) 0) {
- addJob(gi->type, etv->pid);
- }
-
- if (etv->wait) {
- waitForJob(etv->pid);
- }
-
- free(cmd);
-
- } else if (*(etv->execCommand) != PIPE_CHAR) {
-
- /* ===== Data copied to temp file ===== */
-
- int forkError;
- BOOLEAN okSoFar;
-
- getTempFile(tempName);
-
- /* find the file name suffix which may provide additional
- info on file type to the implementor -- if possible */
-
- path = vStringValue(&(gi->selector));
- suffix = rindex(path, '.');
- if (suffix != NULL) {
-
- /* find length of ".xxx". If it's 4 or fewer characters
- after the dot, assume that it's a meaningful suffix
- and copy it to the end of the temp file name. */
-
- int nch = strlen(suffix);
-
- if (nch <= 4) {
- strcat (tempName, suffix);
- }
- }
-
- if ((tempFD = open(tempName, O_WRONLY | O_CREAT, TMP_FILE_MODE))
- < 0) {
- perror("issueCommand");
- (void) removeStatusPanel();
-
- sprintf(errorString,
- "Cannot open the temporary file %s", tempName);
- showError(errorString);
- fprintf (stderr, "%s\n", errorString);
- return FALSE;
- }
-
- okSoFar = GI_copyFromNet(tempFD, gi, (char *) NULL);
-
- close(tempFD);
-
- if (! okSoFar) {
- unlink (tempName);
- return FALSE;
- }
-
- cmd = editCommand(gi, etv->execCommand, tempName, tempName);
- /* fprintf (stderr, "\tExecute the command\n\t%s\n\n", cmd); */
-
- sprintf(message, "Working on %s, please stand by",
- gi->sc->typeName);
- showStatus(message, STAT_TEMP_MESSAGE, (char *) NULL, 0);
-
- if ((etv->pid =
- forkAndExec(tildePath(cmd), tempName, &forkError))
- == 0) {
- etv->failed = TRUE;
- sprintf(message,
- "Error trying to start command for \'%s\' (error %d)\n\'%s\'\n",
- sc->typeName, errno, cmd);
- showError(message);
- }
-
- if (etv->pid != (PID_TYPE) 0) {
- addJob(gi->type, etv->pid);
- }
-
- if (etv->wait) {
- waitForJob(etv->pid);
- }
-
- free(cmd);
-
- } else { /* pipe data to command */
-
- /* ===== Data comes from a pipe ===== */
-
- int *forkError;
-
- cmd = editCommand(gi, etv->execCommand, "", (char *) NULL);
- /* fprintf (stderr, "\tExecute the command\n\t%s\n\n", cmd); */
-
- sprintf(message, "Working on %s, please stand by",
- gi->sc->typeName);
- showStatus(message, STAT_TEMP_MESSAGE, (char *) NULL, 0);
-
- if ((etv->pid =
- forkAndPipe(tildePath(cmd+1), gi, &forkError))
- == 0) {
- etv->failed = TRUE;
- sprintf(message,
- "Error trying to start command for \'%s\' (error %d)\n\'%s\'\n",
- sc->typeName, errno, cmd);
- showError(message);
- }
-
- if (etv->pid != (PID_TYPE) 0) {
- addJob(gi->type, etv->pid);
- }
-
- if (etv->wait) {
- waitForJob(etv->pid);
- }
-
- free(cmd);
- }
-
- return TRUE;
- }
-
-
- /* getExtTypeValue
- return the extended type value record for a given type letter, or
- NULL if it does not exist. */
-
- static extTypeValue *
- getExtTypeValue(wanted)
- char wanted;
- {
- extTypeValue *etv;
-
- for (etv=etvList;
- (etv != (extTypeValue *) NULL && etv->type != wanted);
- etv=etv->next) ;
-
- return etv;
- }
-
-
- /* GIExtend_init
- initialize extend type class - host access list and prefix. */
-
- void
- GIExtend_init()
- {
- char *s = appResources->extendedTypes;
- char extType[6];
- typeResources *typeRes;
- scInfo *scRec;
- char message[MESSAGE_STRING_LEN];
-
- if (s == (char *) NULL || *s == NULLC) {
- return;
- }
-
- GU_makePrefix(prefixExtend, appResources->prefixUnknown);
-
- strcpy(extType, "type ");
- while (*s != NULLC) {
- if (*s == ' ' || *s == '\t') {s++; continue;}
-
- /* process new type; receive back a static struct */
-
- extType[4] = *s;
- typeRes = getTypeResources(extType, EXT_CLASS);
-
- /* look for "sameAs" - if NOT present, copy EXTEND subclass */
-
- if (typeRes->sameAs == (String) NULL ||
- *(typeRes->sameAs) == NULLC) {
- extTypeValue *etv;
- scRec = GU_copySubclassRecord(A_EXTENDED);
-
- /* copy execCommand, useTempFile, wait, singleThread
- to a new record. */
-
- etv = (extTypeValue *) malloc (sizeof(extTypeValue));
- etv->type = *s;
- if (typeRes->execCommand != (char *) NULL) {
- etv->execCommand =
- (char *) malloc (strlen(typeRes->execCommand) + 1);
- strcpy(etv->execCommand, typeRes->execCommand);
- } else {
- etv->execCommand = (char *) NULL;
- }
- etv->wait = typeRes->wait;
- etv->failed = FALSE;
- etv->pid = (PID_TYPE) 0;
- etv->next = etvList;
-
- etvList = etv;
-
- /* "sameAs" given - use internal or extended type */
-
- } else if (*(typeRes->sameAs + 1) != NULLC) {
- sprintf (message,
- "Extended type \'%c\' - \'sameAs\' %s (not \'%s\')",
- *s, "resource must be a single character",
- typeRes->sameAs);
- fprintf (stderr, "%s\n", message);
- } else {
- extTypeValue *oldEtv = getExtTypeValue(*(typeRes->sameAs));
-
- scRec = GU_copySubclassRecord(*(typeRes->sameAs));
-
- if (oldEtv != (extTypeValue *) NULL) {
- extTypeValue *etv;
-
- /* copy extTypeValue to complete the "sameAs" processing */
-
- etv = (extTypeValue *) malloc (sizeof(extTypeValue));
- bcopy((char *) oldEtv, (char *) etv, sizeof(extTypeValue));
-
- /* then, replace the type and execCommand
- in the new record. */
-
- etv->type = *s;
- if (typeRes->execCommand != (char *) NULL) {
- etv->execCommand =
- (char *) malloc (strlen(typeRes->execCommand) + 1);
- strcpy(etv->execCommand, typeRes->execCommand);
- }
-
- etv->failed = FALSE;
- etv->pid = (PID_TYPE) 0;
- etv->next = etvList;
-
- etvList = etv;
- }
- }
-
- if (typeRes->description != (String) NULL) {
- scRec->typeName = malloc(strlen(typeRes->description) + 1);
- strcpy(scRec->typeName, typeRes->description);
- }
- if (typeRes->prefix != (String) NULL) {
- scRec->typePrefix = (char *) malloc(PREFIX_LEN);
- GU_makePrefix(scRec->typePrefix, typeRes->prefix);
- }
- if (typeRes->servers != (String) NULL) {
- scRec->hostList = (accessList *) malloc(sizeof(accessList));
- *(scRec->hostList) = GU_createAccessList(typeRes->servers);
- }
-
- if (typeRes->dataType != copyTypeUnspec) {
- scRec->copyDataType = typeRes->dataType;
- if (scRec->copyDataType == copyTypeNone) {
- scRec->copyProc = GI_noCopyItem;
- } else {
- scRec->copyProc = GI_copyToFile;
- }
- }
-
- GU_registerNewType(*s, scRec);
-
- s++;
- }
-
- return;
- }
-
-
- /* GIExtend_access
- check the accessability of an extended type file selection */
-
- BOOLEAN
- GIExtend_access(gi)
- gopherItemP gi;
- {
- BOOLEAN result;
-
- if (gi->sc->hostList == NULL || *(gi->sc->hostList) == NULL ||
- GU_checkAccess(gi->host, *(gi->sc->hostList))) {
- result = TRUE;
- }else {
- result = FALSE;
- }
-
- return result;
- }
-
-
- /* GIExtend_process
- process an extended type file selection */
-
- BOOLEAN
- GIExtend_process(gi)
- gopherItemP gi;
- {
- BOOLEAN result;
- extTypeValue *etv = getExtTypeValue(gi->type);
- char message[MESSAGE_STRING_LEN];
-
-
- /* fprintf (stderr, "Process a type %c.\n", gi->type); */
-
- if (etv == (extTypeValue *) NULL) {
- return FALSE;
- }
-
- if (etv->execCommand == (char *) NULL ||
- strlen(etv->execCommand) == 0) {
- fprintf (stderr,
- "Type %c item (%s) - nothing to do\n",
- gi->type, gi->sc->typeName);
- return FALSE;
- }
-
- /* fprintf (stderr, "Process a type %c.\n\tRaw command:\t%s\n",
- gi->type, etv->execCommand); */
-
- sprintf (message, "Trying to start %s %s",
- (GU_isVowel(gi->sc->typeName) ? "an" : "a"), gi->sc->typeName);
-
- showStatus(message, STAT_TEMP_MESSAGE, gi->host, gi->port);
-
-
- result = issueCommand(gi, etv);
-
- return result;
- }
-